package com.ruoyi.business.controller;

import com.alibaba.fastjson2.JSON;
import com.ruoyi.business.domain.ClassInfo;
import com.ruoyi.business.domain.School;
import com.ruoyi.business.domain.dto.*;
import com.ruoyi.business.domain.enums.GenderEnum;
import com.ruoyi.business.domain.enums.UserTypeEnum;
import com.ruoyi.business.domain.vo.FrontLoginVO;
import com.ruoyi.business.domain.vo.FrontUserInfoVO;
import com.ruoyi.business.service.IClassInfoService;
import com.ruoyi.business.service.ISchoolService;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.domain.SysUserRole;
import com.ruoyi.system.service.ISysRoleService;
import com.ruoyi.system.service.ISysUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.business.domain.User;
import com.ruoyi.business.service.IUserService;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo;

/**
 * 用户Controller
 * 
 * @author lcz
 * @date 2025-02-21
 */
@Api(tags = "用户相关接口")
@RestController
@RequestMapping("/business/user")
public class UserController extends BaseController
{
    @Autowired
    private IUserService userService;

    @Autowired
    private ISysUserService sysUserService;

    @Autowired
    private TokenService tokenService;

    @Autowired
    private IClassInfoService classInfoService;

    @Autowired
    private ISchoolService schoolService;

    /**
     * 查询用户列表
     */
//    @ApiIgnore
    @ApiOperation(value = "后台----查询用户列表", position = 1)
//    @PreAuthorize("@ss.hasPermi('business:user:list')")
    @GetMapping("/list")
    public TableDataInfo list(User user)
    {
        SysUser sysUser = SecurityUtils.getLoginUser().getUser();
        Long roleId = sysUser.getRoles().get(0).getRoleId();
        if (!sysUser.isAdmin()){
            user.setSchoolId(sysUser.getSchoolId());
            if (roleId.toString().equals("120")){
                if (!user.getType().equals(UserTypeEnum.PARENT.getKey())){
                    ClassInfo param = new ClassInfo();
                    param.setTeacherId(sysUser.getUserId());
                    List<ClassInfo> classInfoList = classInfoService.selectClassInfoList(param);
                    List<Long> classIdList = classInfoList.stream().map(ClassInfo::getId).collect(Collectors.toList());
                    user.setClassIdList(classIdList);
                }
            }
        }
        startPage();
        List<User> list = userService.selectUserList(user);
        return getDataTable(list);
    }

    /**
     * 导出用户列表
     */
//    @ApiIgnore
    @ApiOperation(value = "后台----导出用户列表", position = 1)
//    @PreAuthorize("@ss.hasPermi('business:user:export')")
    @Log(title = "用户", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, User user)
    {
        SysUser sysUser = SecurityUtils.getLoginUser().getUser();
        Long roleId = sysUser.getRoles().get(0).getRoleId();
        if (!sysUser.isAdmin()){
            user.setSchoolId(sysUser.getSchoolId());
            if (roleId.toString().equals("120")){
                if (!user.getType().equals(UserTypeEnum.PARENT.getKey())){
                    ClassInfo param = new ClassInfo();
                    param.setTeacherId(sysUser.getUserId());
                    List<ClassInfo> classInfoList = classInfoService.selectClassInfoList(param);
                    List<Long> classIdList = classInfoList.stream().map(ClassInfo::getId).collect(Collectors.toList());
                    user.setClassIdList(classIdList);
                }
            }
        }
        List<User> list = userService.selectUserList(user);
        if(user.getType().equals(UserTypeEnum.STUDENT.getKey())){
            List<StudentDTO> studentDTOS = JSON.parseArray(JSON.toJSONString(list), StudentDTO.class);
            ExcelUtil<StudentDTO> util = new ExcelUtil<StudentDTO>(StudentDTO.class);
            util.exportExcel(response, studentDTOS, "学生数据");
        }else {
            List<ParentDTO> parentDTOS = JSON.parseArray(JSON.toJSONString(list), ParentDTO.class);
            ExcelUtil<ParentDTO> util = new ExcelUtil<ParentDTO>(ParentDTO.class);
            util.exportExcel(response, parentDTOS, "家长数据");
        }
    }

    /**
     * 获取用户详细信息
     */
    @ApiOperation(value = "后台----获取用户详细信息", position = 1)
//    @PreAuthorize("@ss.hasPermi('business:user:query')")
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id)
    {
        return success(userService.selectUserById(id));
    }

    /**
     * 新增用户
     */
    @ApiOperation(value = "后台----新增用户", position = 1)
//    @PreAuthorize("@ss.hasPermi('business:user:add')")
    @Log(title = "用户", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody User user)
    {
        return toAjax(userService.insertUser(user));
    }

    /**
     * 修改用户
     */
    @ApiOperation(value = "后台----修改用户", position = 1)
//    @PreAuthorize("@ss.hasPermi('business:user:edit')")
    @Log(title = "用户", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody User user)
    {
        return toAjax(userService.updateUser(user));
    }

    /**
     * 删除用户
     */
    @ApiOperation(value = "后台----删除用户", position = 1)
//    @PreAuthorize("@ss.hasPermi('business:user:remove')")
    @Log(title = "用户", businessType = BusinessType.DELETE)
	@DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable Long[] ids)
    {
        return toAjax(userService.deleteUserByIds(ids));
    }

    /**
     * 导入接口
     */
    @ApiOperation("后台----导入学生数据")
    @PostMapping("/importStudentData")
    public AjaxResult importStudentData(MultipartFile file) throws Exception {

        SysUser sysUser = SecurityUtils.getLoginUser().getUser();
//        SysUser sysUser = new SysUser();
//        sysUser.setUserId(129l);
//        sysUser.setSchoolId(14l);
        School school = schoolService.selectSchoolById(sysUser.getSchoolId());
        if (ObjectUtils.isEmpty(school)) {
            return AjaxResult.error("该账号不属于任何学校，无法导入学生信息");
        }

        InputStream inputStream = file.getInputStream();
        ExcelUtil<StudentDTO> util = new ExcelUtil<StudentDTO>(StudentDTO.class);
        List<StudentDTO> studentDTOList = util.importExcel(inputStream);

        User param = new User();
        param.setType("0");
        param.setSchoolId(sysUser.getSchoolId());
        List<User> dataList = userService.selectUserList(param);

        User parent = new User();
        parent.setType("1"); // 假设家长的类型为"1"
        parent.setSchoolId(sysUser.getSchoolId());
        List<User> parentList = userService.selectUserList(parent);
        //TODO: 比较两个列表，以学号、账号、手机号为组合键，找出studentDTOList中有多少数据是dataList中存在的，并返回这些数据的行号

        // 用于存储重复数据的行号
        List<Integer> duplicateRowNumbers = new ArrayList<>();

        try{
            // 创建一个映射，用于快速查找dataList中是否存在相同的组合键
            Map<String, User> existingDataMap = dataList.stream()
                    .collect(Collectors.toMap(
                            student -> student.getStudentNumber(),
                            student -> student
                    ));

            // 遍历导入的studentDTOList，检查是否存在重复数据
            for (int i = 0; i < studentDTOList.size(); i++) {
                StudentDTO studentDTO = studentDTOList.get(i);
                String key = studentDTO.getStudentNumber();
                if (existingDataMap.containsKey(key)) {
                    // 如果存在重复，记录行号（注意：Excel行号从1开始，i从0开始，所以需要加2）
                    duplicateRowNumbers.add(i + 2); // 假设第一行为标题行
                }
            }
        }catch (Exception e){
            return AjaxResult.error("导入失败,请检查:学号、账号、手机号 是否为正确值");
        }

        // 如果有重复数据，返回错误信息和重复的行号
        if (!duplicateRowNumbers.isEmpty()) {
            return AjaxResult.error("以下行号的数据已存在：" + duplicateRowNumbers.toString());
        }

        List<User> userList = JSON.parseArray(JSON.toJSONString(studentDTOList), User.class);

        ClassInfo classParam = new ClassInfo();
        classParam.setSchoolId(sysUser.getSchoolId());
        List<ClassInfo> classInfoList = classInfoService.selectClassInfoList(classParam);
        Map<String,ClassInfo> classInfoMap = classInfoList.stream().collect(Collectors.toMap(classInfo -> classInfo.getGradename() + classInfo.getClassName(), Function.identity()));

        // 将userList转换为Map，手机号和实体分别为键值，以便快速查找
        Map<String, User> parentMap = new HashMap<>();
        if (parentList.size() > 0){
            parentMap = parentList.stream().collect(Collectors.toMap(
                    user-> user.getPhoneNumber(),
                    user -> user
            ));
        }

        if (userList.size() > 0){
            for (User user : userList){
                user.setSchoolId(sysUser.getSchoolId());
                user.setSchoolName(school.getSchoolName());
                user.setPassword(SecurityUtils.encryptPassword("123456"));
                user.setAccount(user.getStudentNumber());
                user.setType("0");
                user.setCreateTime(new Date());
                ClassInfo temp = classInfoMap.get(user.getGradename() + user.getClassName());
                if (ObjectUtils.isEmpty(temp)){
                    return AjaxResult.error("导入失败，"+user.getUserName()+"同学的年级、班级信息有误");
                }
                user.setClassId(temp.getId());
                user.setClassName(temp.getClassName());
                user.setGrade(temp.getGrade());
                user.setGradename(temp.getGradename());
                if (parentList.size() > 0){
                    if (!ObjectUtils.isEmpty(user.getPhoneNumber())){
                        if (parentMap.containsKey(user.getPhoneNumber())){
                            user.setfId(parentMap.get(user.getPhoneNumber()).getId());
                            user.setFName(parentMap.get(user.getPhoneNumber()).getUserName());
                        }
                    }
                }
            }
//            userService.batchInsertUser(userList);
            return userService.batchInsertUserAndBinding(userList);
        }
        return AjaxResult.success();
    }

    /**
     * 导入接口
     */
    @ApiOperation("后台----导入家长数据")
    @PostMapping("/importParentData")
    public AjaxResult importParentData(MultipartFile file) throws Exception {

        SysUser sysUser = SecurityUtils.getLoginUser().getUser();
        School school = schoolService.selectSchoolById(sysUser.getSchoolId());
        if (ObjectUtils.isEmpty(school)) {
            return AjaxResult.error("该账号不属于任何学校，无法导入学生信息");
        }

        InputStream inputStream = file.getInputStream();
        ExcelUtil<ParentDTO> util = new ExcelUtil<ParentDTO>(ParentDTO.class);
        List<ParentDTO> parentDTOList = util.importExcel(inputStream);

        User param = new User();
        param.setType("1"); // 假设家长的类型为"1"
        param.setSchoolId(sysUser.getSchoolId());
        List<User> dataList = userService.selectUserList(param);
        param.setType("0");
        List<User> studentList = userService.selectUserList(param);

        // 用于存储重复数据的行号
        List<Integer> duplicateRowNumbers = new ArrayList<>();

        try {
            // 创建一个映射，用于快速查找dataList中是否存在相同的手机号
            Map<String, User> existingDataMap = dataList.stream()
                    .collect(Collectors.toMap(
                            user -> user.getPhoneNumber(),
                            user -> user
                    ));

            // 遍历导入的parentDTOList，检查是否存在重复数据
            for (int i = 0; i < parentDTOList.size(); i++) {
                ParentDTO parentDTO = parentDTOList.get(i);
                String key = parentDTO.getPhoneNumber();
                if (existingDataMap.containsKey(key)) {
                    // 如果存在重复，记录行号（注意：Excel行号从1开始，i从0开始，所以需要加2）
                    duplicateRowNumbers.add(i + 2); // 假设第一行为标题行
                }
            }
        } catch (Exception e) {
            return AjaxResult.error("导入失败,请检查:手机号是否为正确值");
        }

        // 如果有重复数据，返回错误信息和重复的行号
        if (!duplicateRowNumbers.isEmpty()) {
            return AjaxResult.error("以下行号的数据已存在：" + duplicateRowNumbers.toString());
        }

        List<User> userList = JSON.parseArray(JSON.toJSONString(parentDTOList), User.class);

        if (userList.size() > 0) {
            for (User user : userList) {
                user.setSchoolId(sysUser.getSchoolId());
                user.setSchoolName(school.getSchoolName());
                user.setPassword(SecurityUtils.encryptPassword("123456"));
                user.setType("1"); // 假设家长的类型为"1"
                user.setCreateTime(new Date());
            }
            userService.batchInsertUser(userList);
        }

        if (studentList.size() > 0) {
            // 将userList转换为Map，手机号和实体分别为键值，以便快速查找
            Map<String, User> parentMap = userList.stream().collect(Collectors.toMap(
                    user-> user.getPhoneNumber(),
                    user -> user
            ));
            for (User student : studentList) {
                if (!ObjectUtils.isEmpty(parentMap.get(student.getPhoneNumber()))) {
                    student.setfId(parentMap.get(student.getPhoneNumber()).getId());
                    student.setFName(parentMap.get(student.getPhoneNumber()).getUserName());
                    userService.updateUser(student);
                }
            }
        }

        return AjaxResult.success();
    }

    /** 前端接口 ***************************************************************************************************/
    /** 前端接口 ***************************************************************************************************/
    /** 前端接口 ***************************************************************************************************/

    /**
     * 查询家长名下所有学生列表
     * 接口路径：/user/front/list
     */
    @GetMapping("/front/studentList")
    @ApiOperation(value = "查询家长名下所有学生列表", position = 2)
    public TableDataInfo<User> frontStudentList()
    {
        Long fId = tokenService.getUserId();
        User user = new User();
        user.setType(UserTypeEnum.STUDENT.getKey());
        user.setfId(fId);
        startPage();
        List<User> list = userService.selectUserList(user);
        list.stream().forEach(item -> {
            item.setGender(GenderEnum.fromKey(Integer.valueOf(item.getGender())).getLabel());
        });
        return getDataTable(list);
    }

    /**
     * 通过学生姓名查询学生列表
     * 接口路径：/user/front/list
     */
    @GetMapping("/front/listByName")
    @ApiOperation(value = "通过学生姓名查询学生列表", position = 2)
    public TableDataInfo<User> listByName(@RequestParam("userName") String userName)
    {
        SysUser sysUser = SecurityUtils.getLoginUser().getUser();
        User user = new User();
        user.setType(UserTypeEnum.STUDENT.getKey());
        user.setUserName(userName);
        user.setSchoolId(sysUser.getSchoolId());
        startPage();
        List<User> list = userService.selectUserList(user);
        if (CollectionUtils.isEmpty(list)){
//            return TableDataInfo.fail("查询失败");
            return getDataTable(list);
        }
        list.stream().forEach(item -> {
            item.setGender(GenderEnum.fromKey(Integer.valueOf(item.getGender())).getLabel());
        });
        return getDataTable(list);
    }

    /**
     * 获取用户详细信息
     * 接口路径：/user/front/info
     */
    @ApiOperation(value = "获取用户详细信息", position = 2)
    @PostMapping(value = "/front/userInfo")
    public R<FrontUserInfoVO> frontUserInfo(@Validated @RequestBody FrontUserInfoDTO dto)
    {
        FrontUserInfoVO res = new FrontUserInfoVO();
        Long userId = tokenService.getUserId();
        if (UserTypeEnum.STUDENT.getKey().equals(dto.getUserType())) {
            User user = userService.selectUserById(userId);
            res.setUserName(user.getUserName());
            res.setAvatar(user.getAvatar());
            res.setSchoolName(user.getSchoolName());
            res.setClassName(user.getClassName());
            res.setUserType(dto.getUserType());
            res.setStudentName("学生");
            res.setGender(user.getGender());
            if (!ObjectUtils.isEmpty(user.getGradename())){
                res.setGrade(user.getGradename());
            }
        } else if (UserTypeEnum.PARENT.getKey().equals(dto.getUserType())) {
            User user = userService.selectUserById(userId);
            User student = userService.selectUserById(dto.getStudentId());
            res.setUserName(user.getUserName());
            res.setAvatar(user.getAvatar());
            res.setUserType(dto.getUserType());
            res.setSchoolName(student.getSchoolName());
            res.setClassName(student.getClassName());
            res.setStudentName(student.getUserName());
            res.setGender(user.getGender());
            if (!ObjectUtils.isEmpty(student.getGradename())){
                res.setGrade(student.getGradename());
            }
        }else {
            SysUser sysUser = sysUserService.selectUserById(userId);
            ClassInfo classInfo = classInfoService.selectClassInfoById(dto.getClassId());
            res.setUserName(sysUser.getNickName());
            res.setAvatar(sysUser.getAvatar());
            res.setUserType(dto.getUserType());
            res.setSchoolName(classInfo.getSchoolName());
            res.setClassName(classInfo.getClassName());
            res.setStudentName("教师");
            res.setGender(sysUser.getSex());
            if (!ObjectUtils.isEmpty(classInfo.getGradename())){
                res.setGrade(classInfo.getGradename());
            }
        }
        return R.ok(res);
    }

    /**
     * 修改密码接口
     * 接口路径：/user/front/edit
     */
    @ApiOperation(value = "修改密码接口", position = 2)
    @PostMapping("/front/changePassword")
    public AjaxResult frontChangePassword(@Validated @RequestBody FrontChangePasswordDTO dto)
    {
        Long userId = tokenService.getUserId();
        if (!dto.getNewPassword().equals(dto.getConfirmPassword())) {
            return AjaxResult.error("两次输入的密码不一致");
        }
        if (dto.getUserType().equals(UserTypeEnum.TEACHER.getKey())) {
            SysUser sysUser = sysUserService.selectUserById(userId);
            if (!SecurityUtils.matchesPassword(dto.getOldPassword(),sysUser.getPassword())) {
                return AjaxResult.error("原始密码错误");
            }
            sysUser.setPassword(SecurityUtils.encryptPassword(dto.getNewPassword()));
            sysUserService.updateUser(sysUser);
        }else {
            User user = userService.selectUserById(userId);
            if (!SecurityUtils.matchesPassword(dto.getOldPassword(),user.getPassword())) {
                return AjaxResult.error("原始密码错误");
            }
            user.setPassword(SecurityUtils.encryptPassword(dto.getNewPassword()));
            userService.updateUser(user);
        }

        return AjaxResult.success("修改密码成功");
    }

    /**
     * 小程序登录接口
     */
    @ApiOperation(value = "小程序登录接口" , response = FrontLoginVO.class, position = 2)
    @PostMapping("/front/login")
    public R<FrontLoginVO> frontLogin(@Validated @RequestBody FrontLoginDTO dto){
        FrontLoginVO res = new FrontLoginVO();

        User userParam = new User();
        List<User> users = new ArrayList<>();
        if (!dto.getUserType().equals(UserTypeEnum.TEACHER.getKey())){
            userParam.setAccount(dto.getAccount());
            userParam.setType(dto.getUserType().toString());
            if (!ObjectUtils.isEmpty(dto.getSchoolId())){
                userParam.setSchoolId(dto.getSchoolId());
            }
            users = userService.selectUserList(userParam);
        }
        if(users.size() <= 0){
            //TODO: 教师登录，在教师表里进行查询
            SysUser sysUserParam = new SysUser();
            sysUserParam.setUserName(dto.getAccount());
            List<SysUser> sysUsers = sysUserService.selectList(sysUserParam);
            if (sysUsers.size()<=0){
                return R.fail("系统中没有该账号!");
            }
            SysUser sysUser = sysUserService.selectUserById(sysUsers.get(0).getUserId());
            if (!SecurityUtils.matchesPassword(dto.getPassword(),sysUser.getPassword())){
                return R.fail("密码错误!");
            }
//            List<SysUserRole> userRoleList = sysUserService.selectUserRoleByUserId(sysUser.getUserId());
//            if (userRoleList.size()<=0) {
//                return R.fail("该用户没有小程序权限!");
//            }else {
//                boolean flag = false;
//                for (SysUserRole temp : userRoleList){
//                    if (temp.getRoleId().equals(UserTypeEnum.TEACHER.getKey())){
//                        flag = true;
//                        break;
//                    }
//                }
//                if (!flag){
//                    return R.fail("该用户没有小程序权限!");
//                }
//            }
            //生成token
            LoginUser loginUser = new LoginUser();

            sysUser.setUserType(UserTypeEnum.TEACHER.getKey());
            loginUser.setUserType(UserTypeEnum.TEACHER.getKey());
            loginUser.setUser(sysUser);
            String token = tokenService.createToken(loginUser);

            res.setToken(token);
            res.setUserType(UserTypeEnum.TEACHER.getKey());
            ClassInfo classInfoParam = new ClassInfo();
            classInfoParam.setTeacherId(sysUser.getUserId());
            List<ClassInfo> classInfoList = classInfoService.selectClassInfoList(classInfoParam);
            if (classInfoList.size()>0){
                ClassInfo classInfo = classInfoList.get(0);
                res.setClassId(classInfo.getId());
            }
            return R.ok(res);
        }
        User user = users.get(0);
        //TODO: 判断密码是否相同
        if (!SecurityUtils.matchesPassword(dto.getPassword(),user.getPassword())){
            return R.fail("密码错误!");
        }

        //生成token
        LoginUser loginUser = new LoginUser();
        SysUser sysUser = new SysUser();
        sysUser.setUserId(user.getId().longValue());
        sysUser.setUserName(user.getUserName());
        sysUser.setUserType(user.getType());
        loginUser.setUserType(user.getType());
        loginUser.setUser(sysUser);
        String token = tokenService.createToken(loginUser);

        res.setToken(token);
        res.setUserType(user.getType());
        if (res.getUserType().equals(UserTypeEnum.PARENT.getKey())){
            User parent = new User();
            parent.setfId(user.getId());
            List<User> userList = userService.selectUserList(parent);
            if (userList.size() < 0){
                return R.fail("请先绑定学生信息");
            }
            User student = userList.get(0);
            res.setStudentId(student.getId());
        }else {

        }
        return R.ok(res);
    }

    /**
     * 小程序退出登录
     */
    @ApiOperation(value = "小程序退出登录", position = 2)
    @GetMapping("/logout")
    public R logout(HttpServletRequest request) {
        LoginUser loginUser = tokenService.getLoginUser(request);
        if (StringUtils.isNotNull(loginUser))
        {
            // 删除用户缓存记录
            tokenService.delLoginUser(loginUser.getToken());
        }
        return R.ok("退出成功");
    }
}
